home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i029: Trackutils - utilities to allocate and copy disk tracks, Part01/02
- Message-ID: <11069@xanth.cs.odu.edu>
- Date: 20 Jan 90 15:37:27 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: Eddy Carroll <ECARROLL%vax1.tcd.ie@CUNYVM.CUNY.EDU>
- Lines: 1740
- Approved: tadguy@cs.odu.edu (Tad Guy)
-
- Submitted-by: Eddy Carroll <ECARROLL%vax1.tcd.ie@CUNYVM.CUNY.EDU>
- Posting-number: Volume 90, Issue 029
- Archive-name: util/trackutils/part01
-
- This archive contains two utilities, TCopy and TFile. I've included them
- together because they complement each other quite well.
-
- TCopy is a utility for copying one or more tracks from one disk to another.
- It also has facilities for automatically mounting RAD: which makes it ideal
- for use during bootup (mount RAD: and copy stuff into it all in one go).
-
- TFile reserves a range of tracks on a disk, so that AmigaDOS can't overwrite
- them accidentally. This is particularly useful for protecting some data
- that has been TCopy'd, but it has other applications also.
-
- Source is contained in the src subdirectory within the zoo archive.
-
- Regards,
- Eddy Carroll ecarroll@vax1.tcd.ie
-
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: src src/dosheaders.h src/makefile src/system.h src/tcopy.c
- # src/tiny.a tcopy.doc tfile.doc
- # Wrapped by tadguy@xanth on Sat Jan 20 10:37:16 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test ! -d 'src' ; then
- echo shar: Creating directory \"'src'\"
- mkdir 'src'
- fi
- if test -f 'src/dosheaders.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/dosheaders.h'\"
- else
- echo shar: Extracting \"'src/dosheaders.h'\" \(2177 characters\)
- sed "s/^X//" >'src/dosheaders.h' <<'END_OF_FILE'
- X/*
- X * DOSHEADER.H
- X *
- X * This file contains a few structures which map out the main
- X * AmigaDOS disk structures (root block, directory block etc.)
- X * These are valid for both the old and new filing systems.
- X *
- X * Taken from Betty Clay's article on the differences between the
- X * old FS and new FS under 1.3, in Transactor UK, V1.6, May 1989, and
- X * from the original AmigaDOS Technical Reference manual.
- X */
- X
- X#define BTOC(x) ((void *)((long)(x)<<2)) /* BPTR to C pointer */
- X#define CTOB(x) ((ULONG) ((long)(x)>>2)) /* C pointer to BPTR */
- X
- X/*
- X * Disk block types
- X */
- X
- X#define Type_Short 0x02
- X#define Type_Data 0x08
- X#define Type_List 0x10
- X
- X#define SecType_File 0xfffffffd
- X#define SecType_Root 0x01
- X#define SecType_UserDir 0x02
- X
- Xstruct RootBlock {
- X LONG Type;
- X ULONG OwnKey;
- X ULONG SeqNum;
- X ULONG HtSize;
- X ULONG Nothing1;
- X ULONG Checksum;
- X ULONG HashTable[72];
- X LONG BitmapFlag;
- X ULONG BitmapKeys[25];
- X ULONG BitmapExtend;
- X ULONG DirAltered[3];
- X char Name[40];
- X ULONG DiskAltered[3];
- X ULONG DiskMade[3];
- X ULONG Nothing2;
- X ULONG Nothing3;
- X ULONG Nothing4;
- X LONG SecondaryType;
- X};
- X
- Xstruct UserDirectoryBlock {
- X LONG Type;
- X ULONG OwnKey;
- X ULONG Spare1;
- X ULONG Spare2;
- X ULONG Spare3;
- X LONG Checksum;
- X ULONG HashTable[72];
- X LONG Spare4;
- X LONG Spare5;
- X ULONG Protection;
- X LONG Spare6;
- X char Comment[92];
- X ULONG Created[3];
- X char DirName[36];
- X LONG Spare7[7];
- X ULONG HashChain;
- X ULONG Parent;
- X ULONG Spare8;
- X LONG SecondaryType;
- X};
- X
- Xstruct FileHeaderBlock {
- X LONG Type;
- X ULONG OwnKey;
- X ULONG HighSeq;
- X ULONG DataSize;
- X ULONG FirstBlock;
- X LONG Checksum;
- X ULONG DataBlocks[72];
- X ULONG Spare1;
- X ULONG Spare2;
- X ULONG Protect;
- X ULONG FileSize;
- X char Comment[92];
- X ULONG Date[3];
- X char FileName[36];
- X ULONG Spare3[7];
- X ULONG HashChain;
- X ULONG Parent;
- X ULONG Extension;
- X LONG SecondaryType;
- X};
- X
- Xstruct FileListBlock {
- X LONG Type;
- X ULONG OwnKey;
- X ULONG BlockCount;
- X ULONG DataSize;
- X ULONG FirstBlock;
- X LONG Checksum;
- X ULONG DataBlocks[72];
- X ULONG Unused[47];
- X ULONG Parent;
- X ULONG Extension;
- X LONG SecondaryType;
- X};
- X
- Xstruct DataBlock { /* Old Filing System only */
- X LONG Type;
- X ULONG Header;
- X ULONG SeqNum;
- X ULONG DataSize;
- X ULONG NextData;
- X LONG Checksum;
- X ULONG Data[122];
- X};
- END_OF_FILE
- if test 2177 -ne `wc -c <'src/dosheaders.h'`; then
- echo shar: \"'src/dosheaders.h'\" unpacked with wrong size!
- fi
- # end of 'src/dosheaders.h'
- fi
- if test -f 'src/makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/makefile'\"
- else
- echo shar: Extracting \"'src/makefile'\" \(1005 characters\)
- sed "s/^X//" >'src/makefile' <<'END_OF_FILE'
- X#
- X# Lattice LKM makefile, for Lattice C V5.04
- X#
- X# Tcopy, Tfile (C) Copyright Eddy Carroll, January 1990
- X#
- X
- XSYMBOLS = RAMBO
- XCFLAGS = -cusq -ms -v -j88i -D$(SYMBOLS) # -D3
- X# # Use -D2 if compiling for TraceBack
- XOPT = -O # Optimisation
- X#BFLAGS = sc sd map ram:map addsym
- XBFLAGS = sc sd map ram:map nd
- XASM = lc:asm
- XSTART = tiny.o
- X#START = lib:catch.o
- XLIBS = lib:lc.lib lib:amiga.lib
- X
- X.c.o:
- X lc $(CFLAGS) $(OPT) -Hsystem.sym $*.c
- X.a.o:
- X $(ASM) -isys:include/ -u $*.a
- X.n.doc:
- X nro >$*.doc -ms:an $*.n
- X.h.sym:
- X copy $*.h to ram:t/dummy.c
- X lc $(CFLAGS) -ph -o$*.sym ram:t/dummy.c
- X delete ram:t/dummy.c
- X
- X#
- X# Makefile dependencies
- X#
- XOBJS1 = tcopy.o
- XOBJS2 = tfile.o
- X
- Xall: tiny.o tfile tcopy
- X
- Xtcopy: $(OBJS1)
- X blink from $(START) $(OBJS1) to tcopy $(BFLAGS) lib $(LIBS)
- X
- Xtfile: $(OBJS2)
- X blink from $(START) $(OBJS2) to tfile $(BFLAGS) lib $(LIBS)
- X
- Xsystem.sym: system.h
- Xtcopy.o: tcopy.c system.sym
- Xtfile.o: tfile.c system.sym dosheaders.h
- Xtiny.o: tiny.a
- END_OF_FILE
- if test 1005 -ne `wc -c <'src/makefile'`; then
- echo shar: \"'src/makefile'\" unpacked with wrong size!
- fi
- # end of 'src/makefile'
- fi
- if test -f 'src/system.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/system.h'\"
- else
- echo shar: Extracting \"'src/system.h'\" \(361 characters\)
- sed "s/^X//" >'src/system.h' <<'END_OF_FILE'
- X#include <exec/types.h>
- X#include <exec/ports.h>
- X#include <exec/io.h>
- X#include <exec/memory.h>
- X#include <devices/trackdisk.h>
- X#include <libraries/dos.h>
- X#include <libraries/dosextens.h>
- X#include <libraries/filehandler.h>
- X#include <proto/exec.h>
- X#include <proto/dos.h>
- X#include <ctype.h>
- X#include <string.h>
- X#ifdef RAMBO
- X#include <proto/expansion.h>
- X#endif RAMBO
- END_OF_FILE
- if test 361 -ne `wc -c <'src/system.h'`; then
- echo shar: \"'src/system.h'\" unpacked with wrong size!
- fi
- # end of 'src/system.h'
- fi
- if test -f 'src/tcopy.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/tcopy.c'\"
- else
- echo shar: Extracting \"'src/tcopy.c'\" \(22873 characters\)
- sed "s/^X//" >'src/tcopy.c' <<'END_OF_FILE'
- X/*
- X * TRACKCOPY.C
- X *
- X * (C) Copyright Eddy Carroll 1989
- X *
- X * This program allows you to copy a portion of one disk device to a portion
- X * of another device which has similar sector and track layout, though may
- X * have a different number of cylinders. It is primarily intended to allow
- X * a recoverable ram disk like RAD: to be preloaded directly from floppy
- X * disk at high speed, a track at a time, instead of having to copy in files
- X * manually.
- X *
- X * Usage: tcopy <srcdevice> <destdevice> <start> <stop> <newstart>
- X *
- X * The parameters are as follows (example values are in brackets)
- X *
- X * <srcdevice> The device to copy from (DF0:)
- X * <destdevice> The device to copy to (RAD:)
- X * <start> The starting cylinder on <srcdevice> (60)
- X * <end> The ending cylinder on <srcdevice> (79)
- X * <newstart> The starting cylinder on <destdevice> (0)
- X *
- X * For example, supposing you want to setup a disk that you can load into
- X * a 264K RAD (equals 24 cylinders of 2 tracks of 11 sectors of 512 bytes).
- X * First of all, you setup RAD: manually by mounting it and then copying
- X * in the appropriate files. Then you put a blank formatted disk into
- X * drive 0 and give the command:
- X *
- X * tcopy RAD: DF0: 0 23 56
- X *
- X * Meaning: Copy cylinders 0-23 of RAD: to cylinders 56-79 of DF0:.
- X *
- X * You then add enough files to DF0: to make a minimal boot disk, taking care
- X * not to add more than (56-40 = 16) cylinders of data (or 176K), since
- X * this would cause the data you've just written directly onto the disk
- X * to be overwritten. Then put the command:
- X *
- X * tcopy DF0: RAD: 56 79 0
- X *
- X * into your startup-sequence, and when you reboot, RAD: will be reloaded
- X * with the appropriate information.
- X * ----
- X * An additional option may be compiled in by defining the constant
- X * RAMBO at compile time. When this is done, tcopy will have
- X * some additional options which allow rad: to be automatically mounted
- X * and initialised. This is designed to remove the overhead of having
- X * to do a MOUNT RAD: in your startup-sequence. When this is the case,
- X * the following options may be specified before the rest of the command
- X * line. If none are specified, RAD: is not mounted. Defaults are in ().
- X *
- X * -v<name> Sets RAD: volume name to be <name> ("RAMB0")
- X * -n<name> Sets RAD: device name to be <name> ("RAD") (no colon!)
- X * -d<name> Sets RAD: exec device to be <name> ("ramdrive.device")
- X * -e<txt> Echos <txt> to stdout
- X * -a Always do track copy, even if RAD: already mounted
- X * -f# Sets flags for OpenDevice() to # (0)
- X * -m# Sets BufMemType to # (1)
- X * -p# Sets boot priority to # (-1)
- X * -t# Sets number of tracks(%) to # (10)
- X * -u# Sets unit number of device to be # (0)
- X *
- X * (%) Actually the number of cylinders, but people seem to like to think
- X * of them as tracks.
- X */
- X
- X#define TRUE 1
- X#define FALSE 0
- X#define LASTCHAR(s) (s[strlen(s)-1])
- X
- X#ifndef LATTICE_50
- X#include "system.h"
- X#endif
- X
- Xextern struct DosLibrary *DOSBase;
- X
- Xtypedef struct IORequest IOREQ;
- Xtypedef struct MsgPort MSGPORT;
- Xtypedef struct Process PROC;
- Xtypedef struct StandardPacket STDPKT;
- X
- Xvoid inhibit(MSGPORT *devport, int mode);
- X/*
- X * Structure representing a disk device
- X */
- Xtypedef struct {
- X char *devname; /* Name of exec device for this disk */
- X int isfloppy; /* True if device is trackdisk.device */
- X ULONG unit; /* Unit number of above exec device */
- X ULONG blocksize; /* Number of bytes per block */
- X ULONG blockspertrack; /* Number of blocks/sectors per track */
- X ULONG surfaces; /* Number of tracks per cylinder */
- X ULONG lowcyl; /* Starting cylinder of disk on device */
- X ULONG numcyl; /* Number of cylinders on this disk */
- X} DISKDEV;
- X
- X#ifdef RAMBO
- X/************************** Declarations for RAMBO **************************/
- X
- Xstruct ExpansionBase *ExpansionBase;
- X
- Xchar execname[] = "ramdrive.device";
- Xchar dosname[] = "RAD";
- Xchar *volname = "RAMB0";
- Xint bootpri = -1;
- X
- X/*
- X * Parameter block for mounting RAD:
- X */
- Xstruct MountParamBlock {
- X char *dosname;
- X char *execname;
- X ULONG unit;
- X ULONG flags;
- X ULONG size;
- X ULONG blocksize;
- X ULONG origin;
- X ULONG surfaces;
- X ULONG sectorperblock;
- X ULONG sectorspertrack;
- X ULONG reserved;
- X ULONG prealloc;
- X ULONG interleave;
- X ULONG lowcyl;
- X ULONG highcyl;
- X ULONG numbuffers;
- X ULONG bufmemtype;
- X} mount = {
- X dosname,
- X execname,
- X 0, /* 2: Unit number */
- X 0, /* 3: OpenDevice() flags */
- X
- X /* This is where the environment block starts */
- X 11, /* 4: Table upper bound */
- X 512>>2, /* 5: Number of longwords per block */
- X 0, /* 6: Sector origin - unused */
- X 2, /* 7: Number of surfaces */
- X 1, /* 8: Sectors per block - unused */
- X 11, /* 9: Sectors per track */
- X 2, /* 10: Reserved blocks - boot block */
- X 0, /* 11: Reserved blocks at end */
- X 0, /* 12: Interleave */
- X 0, /* 13: Low cylinder */
- X 10, /* 14: High cylinder */
- X 5 /* 15: Number of buffers */
- X};
- X
- X/*********************** End of declarations for RAMBO *********************/
- X#endif RAMBO
- X
- X/*
- X * Global variables
- X */
- X
- Xchar *srcname; /* AmigaDos name of source device */
- Xchar *destname; /* AmigaDos name of destination device */
- XDISKDEV src[1]; /* Source disk device */
- XDISKDEV dest[1]; /* Destination disk device */
- Xstruct IOStdReq *srcreq; /* Standard request for source device */
- Xstruct IOStdReq *destreq; /* Standard request for destination device */
- XMSGPORT *reqport; /* Message port for replies from devices */
- XMSGPORT *destport; /* Message port of process of dest. device */
- Xvoid *buffer; /* Pointer to data buffer for track r/w */
- Xlong cylsize; /* Size in bytes of a single cylinder */
- Xint srcdevopen; /* True if source exec device is open */
- Xint destdevopen; /* True if destination device is open */
- Xint inhibited; /* True if destination device is inhibited */
- X
- X
- X/*
- X * print()
- X * -------
- X * Outputs a message to stdout
- X */
- Xvoid print(char *s)
- X{
- X Write(Output(), s, strlen(s));
- X}
- X#define print2(s1,s2) (print(s1),print(s2))
- X#define print3(s1,s2,s3) (print(s1),print(s2),print(s3))
- X
- X/*
- X * numtostr()
- X * ----------
- X * Simple little function which returns a pointer to a static string
- X * representation of the passed in number.
- X */
- Xchar *numtostr(int n)
- X{
- X static char s[20];
- X int i = 19;
- X
- X s[19] = '\0';
- X if (n)
- X while (n) {
- X s[--i] = '0' + (n % 10);
- X n /= 10;
- X }
- X else
- X s[--i] = '0';
- X return(&s[i]);
- X}
- X
- X
- X/*
- X * cleanup()
- X * ---------
- X * Closes all opened resources, and exits with specified error code.
- X */
- Xvoid cleanup(int code)
- X{
- X if (buffer)
- X FreeMem(buffer, cylsize);
- X
- X if (srcdevopen) {
- X if (src->isfloppy) { /* Turn off drive motor if floppy disk */
- X srcreq->io_Command = TD_MOTOR;
- X srcreq->io_Length = 0;
- X DoIO((IOREQ *)srcreq);
- X }
- X CloseDevice((IOREQ *)srcreq);
- X }
- X if (destdevopen) {
- X if (dest->isfloppy) { /* Turn off drive motor if floppy disk */
- X destreq->io_Command = TD_MOTOR;
- X destreq->io_Length = 0;
- X DoIO((IOREQ *)destreq);
- X }
- X CloseDevice((IOREQ *)destreq);
- X }
- X
- X if (inhibited)
- X inhibit(destport, FALSE);
- X
- X if (srcreq)
- X DeleteStdIO(srcreq);
- X if (destreq)
- X DeleteStdIO(destreq);
- X
- X if (reqport)
- X DeletePort(reqport);
- X
- X#ifdef RAMBO
- X if (ExpansionBase)
- X CloseLibrary((struct Library *)ExpansionBase);
- X#endif RAMBO
- X
- X exit(code);
- X}
- X
- X
- X/*
- X * chkabort()
- X * ----------
- X * A replacement for Lattice's chkabort(), which doesn't carry all
- X * the extra baggage. If CTRL-C is detected, this function never
- X * returns but instead calls cleanup. Since Lattice's exit() code
- X * may call chkabort(), a check is made to ensure that cleanup()
- X * only gets called once, otherwise there would be a problem if the
- X * user pressed Ctrl-C twice in quick succession.
- X */
- Xvoid chkabort()
- X{
- X static int gotctrlc = FALSE;
- X if (!gotctrlc && (SetSignal(0,0) & SIGBREAKF_CTRL_C)) {
- X gotctrlc = TRUE;
- X print("^C\n");
- X cleanup(20);
- X }
- X}
- X
- X/*
- X * GetVolume()
- X * -----------
- X * This function searches the device list for the named volume, and
- X * fills in the passed DISKDEV structure with information about the
- X * volume. If the named volume is not a device, or is not a disk,
- X * then FALSE is returned. It is not an error to pass in NULL as
- X * a pointer to the DISKDEV structure. In this case, nothing will
- X * be filled in, but TRUE or FALSE will be returned indicating whether
- X * the device is a disk device or not.
- X */
- Xint GetVolume(char *devname, DISKDEV *dev)
- X{
- X struct RootNode *rootnode;
- X struct DosInfo *dosinfo;
- X struct DeviceNode *devnode;
- X struct FileSysStartupMsg *startup;
- X struct DosEnvec *dosenvec;
- X unsigned char *p;
- X int namelen = strlen(devname);
- X
- X if (LASTCHAR(devname) != ':') /* Device names must end with ':' */
- X return (FALSE);
- X /*
- X * First of all, find the device
- X */
- X rootnode = (struct RootNode *)DOSBase->dl_Root;
- X dosinfo = (struct DosInfo *)BADDR(rootnode->rn_Info);
- X devnode = (struct DeviceNode *)BADDR(dosinfo->di_DevInfo);
- X
- X Forbid(); /* Make sure list doesn't change while we scan it */
- X
- X while (devnode != NULL) {
- X p = (unsigned char *)BADDR(devnode->dn_Name)+1;
- X if (!strnicmp(devname, p, namelen-1)) { /* Don't compare the ':' */
- X /*
- X * Matched name successfully. Now check if it's a device.
- X * Note that we carry on searching if it's not a device
- X * (rather than returning FALSE immediately) since there
- X * may be a volume called RAD: as well as a device called
- X * RAD:, for example.
- X */
- X if (devnode->dn_Type == DLT_DEVICE) {
- X if (devnode->dn_Startup < 20) /* Is there a startup bit? */
- X goto notfound; /* If not, not disk device */
- X /* Eek! A GOTO! */
- X
- X startup = (struct FileSysStartupMsg *)
- X BADDR(devnode->dn_Startup);
- X
- X if (dev) {
- X dev->devname = ((char *)BADDR(startup->fssm_Device))+1;
- X dev->isfloppy = (!strcmp(TD_NAME, dev->devname));
- X dev->unit = startup->fssm_Unit;
- X }
- X
- X if (startup->fssm_Environ < 20)
- X goto notfound;
- X /* Another GOTO! The Earth will end in 5 seconds... */
- X
- X dosenvec = (struct DosEnvec *)BADDR(startup->fssm_Environ);
- X
- X if (dev) {
- X dev->blocksize = dosenvec->de_SizeBlock << 2;
- X dev->blockspertrack = dosenvec->de_BlocksPerTrack;
- X dev->surfaces = dosenvec->de_Surfaces;
- X dev->lowcyl = dosenvec->de_LowCyl;
- X dev->numcyl = (dosenvec->de_HighCyl -
- X dosenvec->de_LowCyl) + 1;
- X }
- X Permit();
- X return (TRUE);
- X }
- X }
- X devnode = (struct DeviceNode *)BADDR(devnode->dn_Next);
- X }
- Xnotfound:
- X Permit();
- X return (FALSE);
- X}
- X
- X/*
- X * help()
- X * ------
- X * Prints out a help message about tcopy
- X */
- Xvoid help()
- X{
- X print(
- X"Tcopy (C) Copyright Eddy Carroll, January 1990. Freely distributable.\n"
- X);
- X#ifdef RAMBO
- X#define print13(a,b,c,d,e,f,g,h,i,j,k,l,m) (print3(a,b,c),print3(d,e,f),\
- X print3(g,h,i),print3(j,k,l),print(m))
- Xprint13(
- X"Usage: tcopy <flags> <from> <to> <start> <end> <newstart>\n\n",
- X" <flags> If any of the following are included, then RAD: will be\n",
- X" automatically mounted when tcopy is run:\n\n",
- X" -v<name> Sets RAD: volume name to be <name> (\"RAMB0\")\n",
- X" -n<name> Sets RAD: device name to be <name> (\"RAD\")\n",
- X" -d<name> Use exec device <name> (\"ramdrive.device\")\n",
- X" \"-e<txt>\" Prints <txt> to stdout\n",
- X" -a Do trackcopy, even if RAD: already mounted\n",
- X" -f# Sets flags for OpenDevice() to # (0)\n",
- X" -m# Sets BufMemType to # (1)\n",
- X" -p# Sets boot priority to # (-1)\n",
- X" -t# Sets number of tracks to # (10)\n",
- X" -u# Sets unit number of exec device to # (0)\n\n"
- X);
- X#else
- X print("Usage: tcopy <from> <to> <start> <end> <newstart>\n\n");
- X#endif RAMBO
- X print(" <from> Device to copy from (e.g. DF0:)\n");
- X print(" <to> Device to copy to (e.g. RAD:)\n");
- X print(" <start> Cylinder to start reading from (e.g. 70)\n");
- X print(" <end> Cylinder to end reading at (e.g. 79)\n");
- X print(" <newstart> Cylinder to start writing at (e.g. 0)\n");
- X}
- X
- X
- X/*
- X * opendevs()
- X * ----------
- X * Opens the source and destination devices, allocates buffer for
- X * reading and writing etc. Note that if either device is a floppy
- X * drive, the buffer must be allocated in chip memory or trackdisk.device
- X * won't be able to blit into it.
- X */
- Xvoid opendevs()
- X{
- X long memflags = 0;
- X
- X if (src->isfloppy || dest->isfloppy)
- X memflags |= MEMF_CHIP;
- X
- X cylsize = src->blocksize * src->blockspertrack * src->surfaces;
- X buffer = AllocMem(cylsize, memflags);
- X if (!buffer) {
- X print("Not enough memory for track buffer\n");
- X cleanup(20);
- X }
- X
- X reqport = (MSGPORT *)CreatePort(0,0);
- X if (!reqport) {
- X print("Couldn't allocate message port\n");
- X cleanup(20);
- X }
- X
- X srcreq = CreateStdIO(reqport);
- X destreq = CreateStdIO(reqport);
- X if (!srcreq || !destreq) {
- X print("Couldn't allocate IO request - memory is low!\n");
- X cleanup(20);
- X }
- X
- X if (OpenDevice(src->devname, src->unit, (IOREQ *)srcreq, 0L)) {
- X print3("Can't open source ", src->devname, "\n");
- X cleanup(20);
- X }
- X srcdevopen = TRUE;
- X
- X if (OpenDevice(dest->devname, dest->unit, (IOREQ *)destreq, 0L)) {
- X print3("Can't open destination ", dest->devname, "\n");
- X cleanup(20);
- X }
- X destdevopen = TRUE;
- X}
- X
- X/*
- X * copytracks()
- X * ------------
- X * This is where the actual work gets done. Tracks (cylinders actually)
- X * are copied from start to end on the source device to newstart on
- X * the destination device.
- X */
- Xvoid copytracks(int start, int end, int newstart)
- X{
- X int cyl, retry, numcyls = (end - start) + 1;
- X
- X for (cyl = 0; cyl < numcyls; cyl++) {
- X /*
- X * First read in track from source device
- X */
- X for (retry = 0; retry < 3; retry++) {
- X chkabort();
- X srcreq->io_Command = CMD_READ;
- X srcreq->io_Length = cylsize;
- X srcreq->io_Offset = (src->lowcyl + cyl + start) * cylsize;
- X srcreq->io_Data = buffer;
- X if (!DoIO((IOREQ *)srcreq))
- X break; /* Succeeded, so break out of loop */
- X }
- X if (retry == 3) {
- X print3("Error reading track ", numtostr(cyl+start)," from disk\n");
- X cleanup(20);
- X }
- X
- X /*
- X * Now write out track to destination device
- X */
- X for (retry = 0; retry < 3; retry++) {
- X chkabort();
- X destreq->io_Command = CMD_WRITE;
- X destreq->io_Length = cylsize;
- X destreq->io_Offset = (dest->lowcyl + cyl + newstart) * cylsize;
- X destreq->io_Data = buffer;
- X if (!DoIO((IOREQ *)destreq))
- X break; /* Succeeded */
- X }
- X if (retry == 3) {
- X print3("Error writing track ", numtostr(cyl), " to disk\n");
- X cleanup(20);
- X }
- X }
- X}
- X
- X
- X/*
- X * SendPacket()
- X * ------------
- X * ``Sort of'' simulates the ARP SendPacket() routine which sends
- X * a packet to AmigaDos, and gets a reply if appropriate. What is
- X * passed in is the action to be executed (one of the ACTION_xxx
- X * definitions in dosextens.h), a pointer to a longword array of 7
- X * arguments to be passed to the device, and the msgport of the device
- X * as returned by DeviceProc("DF0:") for example. If result is non-NULL
- X * then it should be a pointer to a two element array of ULONGs, and it
- X * fills in the 0th element with the primary result, and the the
- X * 1st element with the secondary result.
- X */
- Xint SendPacket(ULONG action, void *args, MSGPORT *devport, ULONG *result)
- X{
- X PROC *proc = (PROC *)FindTask(NULL);
- X STDPKT *packet;
- X
- X packet = (STDPKT *)AllocMem(sizeof(STDPKT), MEMF_CLEAR | MEMF_PUBLIC);
- X if (!packet)
- X return (FALSE);
- X packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt;
- X packet->sp_Pkt.dp_Link = &packet->sp_Msg;
- X packet->sp_Pkt.dp_Port = &proc->pr_MsgPort;
- X packet->sp_Pkt.dp_Type = action;
- X memcpy(&packet->sp_Pkt.dp_Arg1, args, sizeof(ULONG) * 7);
- X
- X /*
- X * Okay, we've done the necessary magic to create an AmigaDos
- X * packet lookalike (thanks to Matt Dillon in Transactor V1.1).
- X * Now we send the message to the Dos process, and get the reply.
- X * Then our message will be filled in with the response from the
- X * Dos process.
- X */
- X PutMsg(devport, (struct Message *)packet);
- X WaitPort(&proc->pr_MsgPort);
- X GetMsg(&proc->pr_MsgPort);
- X if (result) {
- X result[0] = packet->sp_Pkt.dp_Res1;
- X result[1] = packet->sp_Pkt.dp_Res2;
- X }
- X FreeMem(packet, sizeof(STDPKT));
- X return (TRUE);
- X}
- X
- X
- X
- X/*
- X * inhibit()
- X * ---------
- X * This function inhibits (if mode is TRUE) or hibits (if mode is FALSE)
- X * (is hibit the opposite of inhibit? Hmmm...) the specified device.
- X */
- Xvoid inhibit(MSGPORT *devport, int mode)
- X{
- X ULONG pktargs[7];
- X int i;
- X
- X pktargs[0] = mode; /* Select inhibit or opposite */
- X for (i = 1; i < 7; i++) /* Clear other arguments */
- X pktargs[i] = 0;
- X
- X if (!SendPacket(ACTION_INHIBIT, pktargs, devport, NULL)) {
- X print("Couldn't send inhibit packet to device\n");
- X cleanup(20);
- X }
- X}
- X
- X
- X#ifdef RAMBO
- X/*
- X * mountramdisk()
- X * --------------
- X * This procedure simply mounts the device specified in the mount
- X * parameter block.
- X */
- Xint mountramdisk()
- X{
- X struct DeviceNode *devnode;
- X long args[7];
- X int i;
- X char *diskname;
- X MSGPORT *devport;
- X static char dosname[200]; /* Temporary storage for dos device name */
- X
- X ExpansionBase = (struct ExpansionBase *)
- X OpenLibrary("expansion.library", 0L);
- X if (!ExpansionBase) {
- X print("Couldn't open expansion.library\n");
- X cleanup(20);
- X }
- X
- X devnode = MakeDosNode(&mount);
- X if (!devnode)
- X return (FALSE);
- X
- X AddDosNode(bootpri, ADNF_STARTPROC, devnode);
- X
- X /*
- X * Now we've mounted the device, let's try and rename it to
- X * something different.
- X */
- X strcpy(dosname, mount.dosname);
- X strcat(dosname, ":");
- X devport = (MSGPORT *)DeviceProc(dosname);
- X if (!devport)
- X return (FALSE);
- X for (i = 1; i < 7; i++)
- X args[i] = 0;
- X /*
- X * Some horrible messing around to make a BSTR
- X */
- X diskname = AllocMem(strlen(volname)+1,MEMF_PUBLIC);
- X strcpy(diskname+1, volname);
- X *diskname = strlen(volname);
- X args[0] = ((long)diskname)>>2;
- X if (!SendPacket(ACTION_RENAME_DISK, args, devport, NULL))
- X print("(Couldn't relabel disk\n");
- X /* Don't return an error, even if SendPacket failed! */
- X FreeMem(diskname, strlen(volname)+1);
- X return (TRUE);
- X}
- X#endif RAMBO
- X
- X
- X/*
- X * mainline()
- X * ----------
- X */
- Xvoid main(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X unsigned int start, end, newstart; /* Cylinder numbers */
- X
- X#ifdef RAMBO
- X/************************* Start of RAMBO Stuff ***************************/
- X
- X int doload = FALSE; /* If true, always copy to device even if mounted */
- X
- X if (argc > 1 && argv[1][0] == '-') { /* Handle Rambo options */
- X static char tempname[200];
- X while (argc > 1 && argv[1][0] == '-') {
- X char *str = &argv[1][2]; /* Have handy ptr to string */
- X int num = atoi(str); /* Have parameter ready */
- X
- X switch (argv[1][1]) {
- X
- X case 'v': /* Set volume name */
- X volname = str;
- X break;
- X
- X case 'n': /* Set device name */
- X /* Strip trailing ':' */
- X if (LASTCHAR(str) == ':')
- X LASTCHAR(str) = '\0';
- X mount.dosname = str;
- X break;
- X
- X case 'd': /* Set exec device name */
- X mount.execname = str;
- X break;
- X
- X case 'u': /* Set device unit number */
- X mount.unit = num;
- X break;
- X
- X case 'f': /* Set flags for OpenDevice() */
- X mount.flags = num;
- X break;
- X
- X case 't': /* Set number of tracks/cylinders */
- X mount.highcyl = num - 1;
- X break;
- X
- X case 'm': /* Set memory type */
- X mount.bufmemtype = num;
- X break;
- X
- X case 'p': /* Set boot priority */
- X bootpri = num;
- X break;
- X
- X case 'e': /* Echo message to stdout */
- X print2(&argv[1][2], "\n");
- X break;
- X
- X case 'a': /* Force loading into RAD: */
- X doload = TRUE;
- X break;
- X
- X default:
- X print3("Unknown switch ", argv[1], "\n");
- X help();
- X cleanup(5);
- X }
- X argv++;
- X argc--;
- X }
- X
- X /*
- X * Setup defaults for mount okay. Now see if the device is
- X * to be mounted. If it is, then try and mount it. If it was
- X * already mounted, then quit immediately, unless forceload is
- X * in effect.
- X *
- X * Else, see are there any files in RAD:. If there are, quit
- X * immediately (since we are under Kikstart 1.2, and RAD: has
- X * just recovered itself from memory), unless forceload is
- X * in effect.
- X */
- X strcpy(tempname, mount.dosname);
- X strcat(tempname, ":");
- X if (!GetVolume(tempname, NULL)) {
- X
- X if (!mountramdisk()) {
- X print3("Error: Couldn't mount device ",tempname,"\n");
- X cleanup(20);
- X }
- X }
- X /*
- X * Scan device and see if there are files on it.
- X * Do this by seeing if there are any files in
- X * the directory. If there aren't, then we can
- X * force the load, otherwise don't force it.
- X */
- X {
- X struct FileInfoBlock *fib;
- X BPTR lock;
- X
- X fib = AllocMem(sizeof(struct FileInfoBlock), 0L);
- X if (!fib) {
- X print("Out of memory allocating FileInfoBlock!\n");
- X cleanup(20);
- X }
- X lock = Lock(tempname, ACCESS_READ);
- X if (lock) {
- X if (Examine(lock, fib)) {
- X if (!ExNext(lock, fib))
- X doload = TRUE;
- X }
- X UnLock(lock);
- X }
- X FreeMem(fib, sizeof(struct FileInfoBlock));
- X }
- X
- X /*
- X * Now see if after all that, we still want to go
- X * ahead with the load into RAD:. If not, then just
- X * exit silently (to let the startup-sequence carry
- X * on okay).
- X */
- X if (!doload)
- X cleanup(0);
- X }
- X
- X/************************* End of RAMBO Stuff ***************************/
- X#endif RAMBO
- X
- X#define NONUM(x) (!isdigit(argv[x][0]))
- X
- X if (argc != 6 || NONUM(3) || NONUM(4) || NONUM(5)) {
- X help();
- X cleanup(5);
- X }
- X
- X srcname = argv[1];
- X destname = argv[2];
- X start = atoi(argv[3]);
- X end = atoi(argv[4]);
- X newstart = atoi(argv[5]);
- X
- X if (!GetVolume(srcname, src)) {
- X print2(srcname, " is not a valid disk device\n");
- X cleanup(20);
- X }
- X
- X if (!GetVolume(destname, dest)) {
- X print2(destname, " is not a valid disk device\n");
- X cleanup(20);
- X }
- X
- X#define NOTSAME(x) (src->x != dest->x)
- X
- X if (NOTSAME(blocksize) || NOTSAME(blockspertrack) || NOTSAME(surfaces)) {
- X print3(srcname, " and ", destname);
- X print(" do not have same track sizes\n");
- X cleanup(20);
- X }
- X
- X if (start > end) {
- X print("Start track is greater than end track.\n");
- X cleanup(20);
- X }
- X
- X if (end >= src->numcyl) {
- X print3("Maximum end track on ", srcname, " is");
- X print2(numtostr(src->numcyl - 1), ".\n");
- X cleanup(20);
- X }
- X
- X if ((newstart + (end - start)) >= dest->numcyl) {
- X print2("There is not room for ", numtostr(1 + end - start));
- X print3(" tracks on ", destname, "\n");
- X cleanup(20);
- X }
- X
- X destport = (MSGPORT *)DeviceProc(destname);
- X if (!destport) {
- X print3("Can't locate process for device ", destname,"\n");
- X cleanup(20);
- X }
- X
- X /*
- X * The two devices are valid, so now open the exec devices which
- X * they use.
- X */
- X opendevs();
- X inhibit(destport, TRUE);
- X inhibited = TRUE;
- X copytracks(start, end, newstart);
- X cleanup(0);
- X}
- END_OF_FILE
- if test 22873 -ne `wc -c <'src/tcopy.c'`; then
- echo shar: \"'src/tcopy.c'\" unpacked with wrong size!
- fi
- # end of 'src/tcopy.c'
- fi
- if test -f 'src/tiny.a' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/tiny.a'\"
- else
- echo shar: Extracting \"'src/tiny.a'\" \(6132 characters\)
- sed "s/^X//" >'src/tiny.a' <<'END_OF_FILE'
- X*:ts=8
- X****************************************************************************
- X* *
- X* TINY.A (C) Copyright Eddy Carroll 1989 *
- X* ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
- X* *
- X* Replacement startup code for Lattice C V5.04. Use instead of c.o *
- X* This has many features stripped out to allow small utilities to have *
- X* as small a filesize as possible. In particular, don't call any of the *
- X* stdio functions. *
- X* *
- X****************************************************************************
- X
- X INCLUDE "exec/types.i"
- X INCLUDE "exec/alerts.i"
- X INCLUDE "exec/nodes.i"
- X INCLUDE "exec/lists.i"
- X INCLUDE "exec/ports.i"
- X INCLUDE "exec/libraries.i"
- X INCLUDE "exec/tasks.i"
- X INCLUDE "libraries/dos.i"
- X INCLUDE "libraries/dosextens.i"
- X INCLUDE "workbench/startup.i"
- X INCLUDE "exec/funcdef.i"
- X INCLUDE "exec/exec_lib.i"
- X INCLUDE "libraries/dos_lib.i"
- X
- XMAXARGS EQU 100 ; Maximum number of command line arguments from CLI
- XAbsExecBase EQU 4 ; Welcome to the only fixed point in the universe
- X
- X* A useful macro to let us call library routines
- Xcallsys macro
- X CALLLIB _LVO\1
- X endm
- X
- X xdef XCEXIT
- X xdef exit
- X xref LinkerDB
- X xref _BSSBAS
- X xref _BSSLEN
- X
- X csect text,0,0,1,2 * xref's after this are 16-bit reloc
- X xref main * Name of C program to start with.
- X
- Xstart:
- X movem.l d1-d6/a0-a6,-(a7)
- XREGSIZE EQU (6+7)*4
- X lea REGSIZE(a7),A5 * Determine old stack pointer
- X move.l a0,a2 * Save command pointer
- X move.l d0,d2 * and command length
- X lea LinkerDB,a4 * Load base register
- X
- X move.l AbsExecBase.W,a6
- X move.l a6,SysBase(A4)
- X move.l a7,_StackPtr(A4) * Save stack ptr
- X
- X suba.l a1,a1
- X callsys FindTask * Find out our task ID
- X move.l d0,a3
- X
- X move.l a5,D0 * get top of stack
- X sub.l 4(a5),D0 * compute bottom
- X add.l #128,D0 * allow for parms overflow
- X move.l D0,_base(A4) * save for stack checking
- X
- X lea DOSName(A4),A1
- X moveq.l #0,D0
- X callsys OpenLibrary
- X move.l D0,DOSBase(A4)
- X bne getcom
- XnoDOS:
- X moveq.l #100,d0
- X bra exit2
- X
- X*------ find command name:
- Xgetcom:
- X move.l pr_CLI(a3),a0
- X add.l a0,a0
- X add.l a0,a0
- X move.l cli_CommandName(a0),a1
- X add.l a1,a1
- X add.l a1,a1
- X
- X*------ collect parameters:
- X move.l d2,d0 * get command line length
- X moveq.l #0,d1
- X move.b (a1)+,d1
- X move.l a1,_ProgramName(A4)
- X add.l d1,d0 * add length of command name
- X addq.l #1,d0 * allow for space after command
- X
- X clr.w -(A7) * set null terminator for command line
- X addq.l #1,D0 * force to even number of bytes
- X andi.w #$fffe,D0 * (round up)
- X sub.l D0,A7 * make room on stack for command line
- X subq.l #2,D0
- X clr.w 0(A7,D0)
- X
- X*------ copy command line onto stack
- X move.l d2,d0 * get command line length
- X subq.l #1,d0
- X add.l d1,d2
- X
- Xcopy_line:
- X move.b 0(A2,D0.W),0(A7,D2.W) * copy command line to stack
- X subq.l #1,d2
- X dbf d0,copy_line
- X move.b #' ',0(a7,d2.w) * add space between command and parms
- X subq.l #1,d2
- X
- Xcopy_cmd:
- X move.b 0(a1,d2.w),0(a7,d2.w) * copy command name to stack
- X dbf d2,copy_cmd
- X move.l a7,a1 * Get pointer to new command line
- X
- X sub.l #(MAXARGS*4),a7 * Reserve space for argv[]
- X move.l a7,a2 * Initialise base into array
- X move.l a2,a3 * Save base of argv
- X moveq #0,d2 * Initialise argc
- X
- X*
- X* From here on down, A1 is pointer into command line
- X*
- Xbuild_argv:
- X bsr.s getnext * Read next character from line
- X bcs.s doquote * If quote, handle
- X beq.s build_argv * If white space, skip over it
- X
- X lea -1(a1),a0 * Get address of this parameter
- X bsr.s bumpargv * Store it to argv[] array
- Xbuild_2:
- X bsr.s getnext * Get next character
- X bne.s build_2 * If not white space, keep looking
- X clr.b -1(a1) * Zero-terminate current argument
- X bra.s build_argv * And go back to get next argument
- X
- Xdoquote:
- X move.l a1,a0 * Get pointer to this argument
- X bsr.s bumpargv * Output it to argv[]
- Xquote_2:
- X bsr.s getnext * Get next character
- X bcc.s quote_2 * If not quote, keep looking
- X clr.b -1(a1) * Zero-terminate current argument
- Xquote_3:
- X bsr.s getnext * Get next character
- X bne.s quote_3 * Skip until space reached
- X beq.s build_argv * Go back and read next argument
- X
- Xbumpargv:
- X move.l a0,(a2)+ * Output ptr to current argument
- X addq #1,d2 * Increment argc
- X cmpi #MAXARGS,d2 * Used up all our arguments yet?
- X bls.s qrts * If not, then return
- X moveq #110,d0 * Else set return code
- X bra.s exit2 * And exit
- X
- X*
- X* Reads next character from command line. If zero, never returns, but
- X* drops into call to main. Else, returns, with C=1 if character is quote,
- X* Z=1 if character is white space.
- X*
- Xgetnext:
- X move.b (a1)+,d0 * Get character from command line
- X beq.s get_2 * Exit if end of line
- X cmp.b #34,d0 * Check if quote
- X beq.s isquote *
- X cmp.b #32,d0 * Check if space
- X beq.s isspace *
- X cmp.b #9,d0 * Or tab
- X beq.s isspace *
- X cmp.b #10,d0 * Or end of line
- Xisspace:
- X andi #$1E,ccr * Clear carry flag, retaining Z
- Xqrts rts
- X
- Xisquote:
- X ori #1,ccr * Set carry flag
- X andi #$FB,ccr * Clear zero flag
- X rts * And return
- X
- Xget_2:
- X move.l a3,-(a7) * Push argv onto stack
- X move.l d2,-(a7) * Push argc onto stack
- X
- X lea _BSSBAS,a3 * get base of BSS
- X moveq #0,d1
- X move.l #_BSSLEN,d0 * get length of BSS in longwords
- X bra.s clr_lp * and clear for length given
- Xclr_bss move.l d1,(a3)+
- Xclr_lp dbf d0,clr_bss
- X
- Xdomain:
- X jsr main(PC) * Call main(argc,argv)
- X moveq.l #0,d0 * Set successful status
- X bra.s exit2
- X
- Xexit:
- X_exit:
- XXCEXIT:
- X move.l 4(SP),d0 * Extract return code
- Xexit2:
- X move.l d0,-(a7)
- X move.l AbsExecBase.W,a6
- X move.l DOSBase(A4),a1
- X callsys CloseLibrary * Close Dos library
- X
- X*------ this rts sends us back to DOS:
- XexitToDOS:
- X MOVE.L (A7)+,D0
- X movea.l _StackPtr(a4),SP * Restore stack ptr
- X movem.l (a7)+,d1-d6/a0-a6
- X rts
- X
- X*-----------------------------------------------------------------------
- X* Global definitions
- X*
- X csect __MERGED,1,,2,2
- X
- X xdef NULL,SysBase,LoadAddress,DOSBase
- X xdef _oserr,_OSERR,_ONBREAK
- X xdef _ProgramName,_StackPtr,_base
- X
- XNULL dc.l 0
- X_base dc.l 0
- X_oserr equ *
- X_OSERR dc.l 0
- X_ONBREAK dc.l 0
- XSysBase dc.l 0
- XLoadAddress dc.l 0
- X_StackPtr dc.l 0
- XDOSBase dc.l 0
- X_ProgramName dc.l 0
- XDOSName dc.b 'dos.library',0
- X
- X END
- END_OF_FILE
- if test 6132 -ne `wc -c <'src/tiny.a'`; then
- echo shar: \"'src/tiny.a'\" unpacked with wrong size!
- fi
- # end of 'src/tiny.a'
- fi
- if test -f 'tcopy.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tcopy.doc'\"
- else
- echo shar: Extracting \"'tcopy.doc'\" \(10599 characters\)
- sed "s/^X//" >'tcopy.doc' <<'END_OF_FILE'
- X
- X TCOPY -- copies tracks from one disk to another
- X
- X (C) Copyright Eddy Carroll 1990. Freely distributable.
- X
- X
- XINTRODUCTION
- X
- X One of the nicer additions that came with Workbench 1.3 was RAD:, the
- X recoverable ram disk. A handy feature of RAD: is that it can be made to
- X look like a floppy disk, and you can then copy an entire disk into it
- X in one go -- much quicker than copying files in seperately.
- X
- X Unfortunately, you need to have an 880K RAD: to do this; since I only
- X have a 2 Meg Amiga, I can't really afford to lose that much memory.
- X Thus, Tcopy was born.
- X
- X Tcopy is essentially a DiskCopy command which will copy a specified
- X range of tracks (actually cylinders, but most people seem to prefer to
- X call them tracks) from one disk to another. Using Tcopy, you can store
- X a complete "dump" of RAD: on your startup disk, and then copy it back
- X into RAD: very rapidly. For example, it takes about 15 seconds to load
- X up my 275K RAD (as opposed to around 45 seconds when the files were
- X being copied in one at a time). This is a loading speed of around
- X 18K/second. So much for the Amiga's "slow" floppy drives :-)
- X
- X To help speed up your startup times even more, Tcopy can automatically
- X mount RAD: (for all you purists who don't think this sort of thing
- X belongs in a track copier, tcopy can be readily compiled without the
- X RAD: handling). If you have just done a reset and RAD: was already in
- X memory, then Tcopy won't bother reloading it unless you specifically
- X ask it to.
- X
- X
- XUSAGE
- X
- X The command template for Tcopy looks like this:
- X
- X tcopy <options> <from> <to> <start> <end> <newstart>
- X
- X The <options> are all to do with RAD: and if you don't specify any
- X of them, Tcopy won't try to mount it. This allows you to use Tcopy for
- X copying tracks between two normal devices (such as DF0: and DF1:)
- X without having RAD: confusing things. I'll discuss the valid options
- X in a little while.
- X
- X <from> and <to> give the source and destination devices respectively
- X that Tcopy is to use. These devices can be different sizes, but they
- X must both have the same track size (i.e. same number of blocks/track
- X and number of surfaces).
- X
- X <start> specifies the track to start copying from, <end> specifies
- X the track to copy up to (and including), and <newstart> specifies
- X the track to start copying to on the destination device.
- X
- X For example, supposing you wanted to use Tcopy to copy a disk from
- X drive 0 to drive 1. You could type
- X
- X tcopy DF0: DF1: 0 79 0
- X
- X meaning "copy tracks 0 to 79 on DF0: to track 0 upwards on DF1:".
- X It should be pointed out however that Tcopy doesn't make a particularly
- X good disk copier, because:
- X
- X - It requires that the destination disk already be formatted
- X - It doesn't verify the data was written properly
- X - It is about twice as slow as DiskCopy when writing to floppy
- X - It doesn't update the root block on the destination disk, so
- X AmigaDOS will see two disks that look identical, and will go
- X a little bit crazy trying to sort it out.
- X
- X Hence, it's probably best to keep Tcopy for loading RAD:, and for
- X copying the odd single track around when needed.
- X
- X
- XOPTIONS
- X
- X Now onto the options which are supported for mounting RAD: Any
- X or all of these options may appear; options which are ommitted get
- X the default values indicated in brackets. Remember that Tcopy will only
- X mount RAD: automatically if at least one of the options is specified.
- X Also, you should have ramdrive.device in your DEVS: directory.
- X
- X -v<name> (RAMB0)
- X Sets the volume name of the mounted device to <name>. This is the
- X name that appears under the disk icon on Workbench.
- X
- X -n<name> (RAD)
- X Sets the AmigaDOS device name of the mounted device to <name>. This
- X is the "real" name, which cannot be altered once set.
- X
- X -e<txt>
- X Outputs <txt> to the screen. This is useful if you want to display
- X a message while the copying takes place. If the message contains
- X any spaces, you will need to surround the entire option with
- X quotation marks. For example, you might use something like this:
- X
- X "-eNow copying startup disk to RAD:"
- X
- X -a
- X Normally, Tcopy will only actually do the diskcopy into RAD: if it
- X finds RAD: has no files after it has been mounted (i.e. it is a
- X cold startup, rather than a reset). The rest of the time, it will
- X mount RAD: and then quit immediately.
- X
- X You may occasionally want to override this behaviour. Specifying -a
- X will tell Tcopy to always copy the disk into RAD: even when it
- X doesn't think its necessary. This could be useful if you have
- X several different startup disks, each containing a different set
- X of files to load into RAD: (one for programming, one for TeX etc.)
- X
- X -t# (10)
- X Sets the number of tracks that RAD: will have, and therefore the
- X amount of memory it will take up. Each track occupies about 11K
- X of memory. In general, you will want to customise this to suit
- X your system rather than leaving it at the default.
- X
- X -p# (-1)
- X Sets the boot priority for RAD:. This is only useful to Kikstart 1.3
- X users who can boot from RAD: (you 1.2 users don't know what you're
- X missing!) The default of -1 means that the Amiga will first try to
- X boot from a floppy disk in drive 0 and if that fails, will then boot
- X from RAD. If you set this value to 127, the Amiga will always
- X boot from RAD: regardless of what's in drive 0.
- X
- X You are unlikely to ever need to use the following options, but they
- X are included for the adventurous to play with. They give you control
- X over several of the fields that normally appear in the mountlist.
- X Don't mess with them unless you know what you are doing!
- X
- X -d<name> (ramdrive.device)
- X Sets the name of the underlying exec device associated with the
- X AmigaDos device.
- X
- X -f# (0)
- X Sets the flags to specify when calling OpenDevice().
- X
- X -m# (1)
- X Specifies the type of memory to use; the default is Public Memory
- X which is basically any memory that happens to be free.
- X
- X
- XCREATING A STARTUP DISK
- X
- X So, now that you know what Tcopy can do, lets get down to essentials.
- X Namely, how to put together a disk that boots up as quickly as possible.
- X
- X My system consists of an A1000 with 1.3 Kikstart, 2 Megs of RAM, and
- X a C Ltd. hard drive (no autoboot). My RAD: is 275K, and contains
- X a fairly stripped down Workbench -- essentially just enough to
- X get the hard drive up and running, and to install my favourite
- X resident utilities (Dmouse, Conman, BlitzFonts and Snap).
- X
- X My startup disk looks like this:
- X
- X Directory of HD_Boot:
- X c
- X devs
- X l
- X libs
- X s
- X Tracks1-25
- X
- X Directory of HD_Boot:c
- X RemRad
- X Tcopy
- X
- X Directory of HD_Boot:devs
- X ramdrive.device
- X system-configuration
- X
- X Directory of HD_Boot:s
- X startup-sequence
- X
- X If you are paying attention, you may have noticed the file Tracks55-79
- X above. This is a special file created by the Tfile program which
- X accompanies Tcopy, and to AmigaDos, it looks as if it occupies
- X tracks 55 to 79 of the disk. This means that I can store my copy of
- X RAD: on these tracks, without having to worry about AmigaDos trying
- X to overwrite it if I go to save a new file on the disk.
- X
- X My startup-sequence looks like this:
- X
- X c:tcopy -t25 -vRAD "-eBooting up 275K RAD..." df0: rad: 1 25 0
- X rad:c/cd rad:
- X rad:c/defdisk rad:
- X rad:c/execute rad:s/startup-sequence
- X
- X The first command is the only one that gets loaded in from disk. It
- X mounts a RAD: with 25 tracks (275K), changes the volume name to RAD:
- X instead of RAMB0: (which I don't like at all), prints a brief message
- X and then copies tracks 1 to 25 of the startup disk to RAD:. I have
- X arranged that RAD: contains enough commands to allow the bootup to
- X be carried on from there.
- X
- X The next command changes the current directory to RAD: (mainly because
- X the execute command lower down will create a temporary file in the
- X current disk, and I want it to do this in RAD: instead of on my
- X write-protected boot disk!) After this, DefDisk does all the necessary
- X assigns to make RAD: look like the bootup disk (so that I can remove
- X the real bootup disk for good, and AmigaDos won't ever ask me to
- X insert it again). DefDisk is a really nice little P.D. program which is
- X well worth hunting down.
- X
- X The final step is to execute the real startup-sequence located in RAD:.
- X This is the same startup-sequence that will get executed when I reset
- X in future (since I am booting from RAD:).
- X
- X If I accidentally reset with my boot disk in DF0:, no harm is done;
- X Tcopy will see that RAD: is already loaded and exit immediately,
- X
- X If I had Kikstart 1.2 instead of 1.3, the only change I would have to
- X make would be booting from my startup disk each time I reset rather
- X than from RAD:. This would still be very fast, since Tcopy will only
- X copy the disk into RAD: the first time I bootup.
- X
- X I actually created the startup disk as follows. First of all, I
- X mounted RAD: manually, and filled it with all the goodies I wanted.
- X Then I formatted a blank disk, and ran Tfile on it to create the
- X dummy file Tracks1-25 so that those tracks would remain free to store
- X the copy of RAD: on. The command I used was:
- X
- X tfile DF0:Tracks1-25 1 25
- X
- X Then I copied RAD: to the disk with Tcopy:
- X
- X tcopy RAD: DF0: 0 24 1
- X
- X Finally, I created the minimal bootdisk listed earlier by copying over
- X all the files and directories needed.
- X
- X The result? It takes just under 25 seconds from a cold reset to load
- X mount and fill the 275K RAD:, and pass control to its startup-sequence.
- X While it's not as nice as booting off a hard drive, it makes booting
- X from floppy a great deal more bearable!
- X
- X
- XRELEASE HISTORY
- X
- X V1.0
- X First release, January 1990. No known bugs, but this will
- X probably change in the future...
- X
- X
- XAUTHOR
- X
- X Please direct any praise, criticism, general suggestions or
- X large sums of money to:
- X
- X Eddy Carroll
- X ecarroll@vax1.tcd.ie (Trinity College, Dublin, Ireland)
- END_OF_FILE
- if test 10599 -ne `wc -c <'tcopy.doc'`; then
- echo shar: \"'tcopy.doc'\" unpacked with wrong size!
- fi
- # end of 'tcopy.doc'
- fi
- if test -f 'tfile.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tfile.doc'\"
- else
- echo shar: Extracting \"'tfile.doc'\" \(5773 characters\)
- sed "s/^X//" >'tfile.doc' <<'END_OF_FILE'
- X
- X TFILE -- reserves tracks on a disk
- X
- X (C) Copyright Eddy Carroll 1990. Freely distributable.
- X
- X
- XINTRODUCTION
- X
- X There are occasionally times when you want highspeed access to floppy
- X disks, and don't want the overhead associated with going through
- X AmigaDos. One example might be a program to play sound samples
- X directly from disk (reading in a track's worth of data at a time).
- X Another example is copying a "minidisk" into RAD: during bootup (see
- X the documentation for TCOPY for more information on this).
- X
- X This is fine in theory, but if you go and start using disk tracks for
- X your own data, sooner or later you're going to overwrite some AmigaDOS
- X information (or AmigaDOS will overwrite your tracks). What you really
- X need is a way to tell AmigaDOS not to use the tracks that you are
- X using.
- X
- X This is in fact exactly what TFILE does (what a coincidence :-)
- X It creates a dummy file on a disk that looks to AmigaDOS as if it
- X contains all the blocks associated with a range of tracks. You can
- X then happily intermix your private data and standard AmigaDOS files
- X without any danger of one corrupting the other. For example, if you
- X have a game that wants direct access to your hard drive, you could
- X reserve a few cylinders for it to use without having to do a complete
- X reformat and partition. Similarly for something like AMax.
- X
- X
- XUSAGE
- X
- X The command template for Tfile looks like this:
- X
- X tfile <pathname> <start> <end>
- X
- X <pathname> is the full AmigaDOS pathname of the file you want to
- X create which will reserve the tracks. You must specify a disk device
- X (such as DF0:) rather than a volume name. You may like to stick the
- X file out of the way in the Devs directory or some such place, called
- X something like TracksX-Y.
- X
- X <start> and <end> specify the range of tracks to be reserved. When
- X you run Tfile, these tracks must not be in use by AmigaDOS or Tfile
- X will complain. Hence, it's a good idea to run Tfile shortly after you
- X have just formatted a disk, and only then copy over any AmigaDOS files
- X you want to use (AmigaDOS will arrange them nicely around your reserved
- X tracks). Obviously, <start> must be less than <end>, and neither can
- X exceed the number of tracks available on the disk. Tracks are numbered
- X from 0 upwards, so the 80 tracks on DF0: are numbered 0 to 79.
- X
- X AmigaDOS usually reserves a few blocks at the start of a disk for
- X private information. The bootblock on floppy disks is a good example
- X of this. If the track range you specify includes these reserved blocks,
- X Tfile will print a warning message. You can safely ignore this -- it is
- X just there to remind you that you need to be careful writing to the
- X tracks you specified so as not to overwrite important information.
- X
- X To make things clearer, a quick example might be useful. Lets suppose
- X you want to reserve the last 10 tracks on a floppy disk for some
- X reason (tracks 70 to 79). Just put the disk in DF0: and say
- X
- X tfile df0:Tracks70-79 70 79
- X
- X and after a few moments of disk access, you will find yourself with
- X a new file which is 107848 bytes in size, and a correspondingly
- X smaller amount of room on the disk.
- X
- X
- XADDITIONAL NOTES
- X
- X Tfile will work with both the old filing system and fast filing system.
- X On the OFS, if you try to display the dummy file, you will see a brief
- X message telling you that it isn't a real file, and describing which
- X tracks it reserves. You will not be able to access anything other
- X than the message, and it's not a good idea to try and fool AmigaDOS
- X into letting you.
- X
- X On the FFS, you will see the same message, but shortly after that will
- X come the actual raw track data itself. This is due to the different
- X ways the OFS and FFS store the data blocks of a file. If you have a
- X file editor such as NewZap, you can even edit the disk blocks directly;
- X with the exception of the initial "message" block, the blocks are
- X arranged in sequence from the start to end track.
- X
- X You can have several different portions of the disk reserved if you
- X like (you might want to reserve almost all of the disk except for a
- X little bit in the middle for the AmigaDOS root block).
- X
- X When you are finished using the tracks, you can release the blocks
- X back to AmigaDOS by deleting the dummy file.
- X
- X You may occasionally have trouble finding free room on a disk. David
- X Gay has written a nice pair of programs which display disk fragmentation
- X and free blocks. These can be found on Fish Disk 278
- X under the collective title `frag'.
- X
- X
- XFUTURE ADDITIONS
- X
- X One thing I would like to add is the ability to read in a list of
- X block numbers from a file and reserve those blocks listed, rather
- X than being restricted to complete tracks. You could then use Tfile
- X to map out bad blocks on hard drives, in conjunction with some
- X program that would actually find such blocks for you. As it is,
- X you could use Tfile to map out bad tracks on AmigaDOS floppies,
- X but given the cost of blank disks these days and the chances of
- X a disk with one bad track developing others, it's not really
- X a sensible gamble.
- X
- X To add block lists would not be too difficult given the current
- X implementation; the only thing needed is time. Unfortunately, I don't
- X have very much of that at the moment, so don't expect them any time soon.
- X
- X
- XRELEASE HISTORY
- X
- X V1.0
- X First release, January 1990. No known bugs, as yet.
- X
- X
- XAUTHOR
- X
- X Please direct any praise, criticism, general suggestions or
- X large sums of money to:
- X
- X Eddy Carroll
- X ecarroll@vax1.tcd.ie (Trinity College, Dublin, Ireland)
- END_OF_FILE
- if test 5773 -ne `wc -c <'tfile.doc'`; then
- echo shar: \"'tfile.doc'\" unpacked with wrong size!
- fi
- # end of 'tfile.doc'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions s should be addressed to ``amiga-request''
- (only use ``amiga'' for submissions) at the above addresses.
-